# ifndef COT_PREPROCESSOR_SEQ_FOR_EACH_H
# define COT_PREPROCESSOR_SEQ_FOR_EACH_H


#include "preprocessor/is_empty.h"
#include "preprocessor/iif.h"
#include "preprocessor/for.h"
#include "preprocessor/elem.h"
#include "preprocessor/seq.h"
#include "preprocessor/size.h"
#include "preprocessor/equal.h"
#include "preprocessor/stringize.h"

#    define COT_PP_SEQ_FOR_EACH(macro, data, seq) COT_PP_SEQ_FOR_EACH_D(macro, data, seq)
#    define COT_PP_SEQ_FOR_EACH_D(macro, data, seq) COT_PP_SEQ_FOR_EACH_DETAIL_CHECK(macro, data, seq)

#    define COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_EXEC(macro, data, seq) COT_PP_FOR((macro, data, seq, COT_PP_SEQ_SIZE(seq)), COT_PP_SEQ_FOR_EACH_P, COT_PP_SEQ_FOR_EACH_O, COT_PP_SEQ_FOR_EACH_M)
#    define COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_EMPTY(macro, data, seq)

#    define COT_PP_SEQ_FOR_EACH_DETAIL_CHECK(macro, data, seq) \
		COT_PP_IIF \
			( \
			COT_PP_SEQ_DETAIL_IS_NOT_EMPTY(seq), \
			COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_EXEC, \
			COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_EMPTY \
			) \
		(macro, data, seq) \

# define COT_PP_SEQ_FOR_EACH_P(r, x) COT_PP_TUPLE_ELEM(4, 3, x)

# define COT_PP_SEQ_FOR_EACH_O(r, x) COT_PP_SEQ_FOR_EACH_O_I x

# define COT_PP_SEQ_FOR_EACH_O_I(macro, data, seq, sz) \
	COT_PP_SEQ_FOR_EACH_O_I_DEC(macro, data, seq, COT_PP_DEC(sz)) \
/**/
# define COT_PP_SEQ_FOR_EACH_O_I_DEC(macro, data, seq, sz) \
	( \
	macro, \
	data, \
	COT_PP_IF \
		( \
		sz, \
		COT_PP_SEQ_FOR_EACH_O_I_TAIL, \
		COT_PP_SEQ_FOR_EACH_O_I_NIL \
		) \
	(seq), \
	sz \
	) \
/**/
# define COT_PP_SEQ_FOR_EACH_O_I_TAIL(seq) COT_PP_SEQ_TAIL(seq)
# define COT_PP_SEQ_FOR_EACH_O_I_NIL(seq) COT_PP_NIL

#    define COT_PP_SEQ_FOR_EACH_M(r, x) COT_PP_SEQ_FOR_EACH_M_IM(r, COT_PP_TUPLE_REM_4 x)
#    define COT_PP_SEQ_FOR_EACH_M_IM(r, im) COT_PP_SEQ_FOR_EACH_M_I(r, im)

# define COT_PP_SEQ_FOR_EACH_M_I(r, macro, data, seq, sz) macro(r, data, COT_PP_SEQ_HEAD(seq))

#    define COT_PP_SEQ_FOR_EACH_R(r, macro, data, seq) COT_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq)
#    define COT_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_R(r, macro, data, seq)

#    define COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_EXEC_R(r, macro, data, seq) COT_PP_FOR_ ## r((macro, data, seq, COT_PP_SEQ_SIZE(seq)), COT_PP_SEQ_FOR_EACH_P, COT_PP_SEQ_FOR_EACH_O, COT_PP_SEQ_FOR_EACH_M)
#    define COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_EMPTY_R(r, macro, data, seq)
#
#    define COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_R(r, macro, data, seq) \
		COT_PP_IIF \
			( \
			COT_PP_SEQ_DETAIL_IS_NOT_EMPTY(seq), \
			COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_EXEC_R, \
			COT_PP_SEQ_FOR_EACH_DETAIL_CHECK_EMPTY_R \
			) \
		(r, macro, data, seq) \


# define COT_PP_COMMA() ,

# endif
